﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using Tracy.CoreLib.Data;
using Tracy.CoreLib;
using System.Collections.Specialized;
using System.Threading;
using CoreLib.Message;
namespace Tracy.Engine
{
    /// <summary>
    /// TracyEngine，主要逻辑在这里实现
    /// </summary>
    public partial class TracyEngine : MessageProcessor
    {
        int downloaderQueueCount = 0;
        void TracyDownloader_OnQueueModified(object sender, TracyGeneralEventArgs e)
        {
            Interlocked.Exchange(ref downloaderQueueCount, Convert.ToInt32(e.Data));
        }

        public event EventHandler<TracyMessageEventArgs> OnMessageProcessed;
        public event EventHandler<TracyGeneralEventArgs> OnQueueModified;
        protected override void CallOnMessageProcessed(object sender, TracyMessageEventArgs e)
        {
            OnMessageProcessed(sender, e);
        }
        protected override void CallOnQueueModified(object sender, TracyGeneralEventArgs e)
        {
            e.Data = Convert.ToInt32(e.Data) + downloaderQueueCount;
            OnQueueModified(sender, e);
        }
        
        #region backup
        //private bool killThreadFlag = false;
        ///// <summary>
        ///// 消息队列线程
        ///// </summary>
        //private Thread threadMessageQueue;

        //private Queue<ITracyMessage> _messageQueue;
        ///// <summary>
        ///// 消息队列
        ///// </summary>
        //private Queue<ITracyMessage> MessageQueue
        //{
        //    get { if (_messageQueue == null)_messageQueue = new Queue<ITracyMessage>(); return _messageQueue; }
        //}

        ///// <summary>
        ///// 消息入队
        ///// </summary>
        //public void EnqueueMessage(ITracyMessage msg)
        //{
        //    lock (this)
        //    {
        //        MessageQueue.Enqueue(msg);
        //    }
        //}

        ///// <summary>
        ///// （独立线程）检查消息队列
        ///// </summary>
        //public void CheckMessageQueue()
        //{
        //    ITracyMessage msg;
        //    while (!killThreadFlag)
        //    {
        //        while (MessageQueue.Count > 0 && !killThreadFlag)
        //        {
        //            msg = null;
        //            lock (this)
        //            {
        //                if (MessageQueue.Count > 0)
        //                {
        //                    msg = MessageQueue.Dequeue();
        //                }
        //            }

        //            if (msg != null)
        //            {
        //                ProcessMessage(msg);
        //                //TODO: 使用自定义的EventArgs
        //                OnMessageProcessed(this, new TracyMessageEventArgs(msg));
        //            }

        //            Thread.Sleep(10);
        //        }
                
        //    }
        //}
        #endregion

        /// <summary>
        /// 发送异常消息
        /// </summary>
        void TracyDownloader_OnException(object sender, EventArgsWithData e)
        {
            OnMessageProcessed(sender, new TracyMessageEventArgs(new ExceptionMessage(sender, (Exception)e.Data)));
        }

        #region 消息处理

        /// <summary>
        /// 按类型分发消息
        /// </summary>
        protected override void ProcessMessage(ITracyMessage msg)
        {
            if (DEBUG_MODE)
            {
                MessageDispatcher(msg);
            }
            else
            {
                try
                {
                    MessageDispatcher(msg);
                }
                catch (Exception e)
                {
                    msg.MessageException = e;
                }
            }
        }

        private void MessageDispatcher(ITracyMessage msg)
        {
            if (msg is IManagedXmlModelMessage) ProcessMessage((IManagedXmlModelMessage)msg);
            else if (msg is UpdateFeedMessage) ProcessMessage((UpdateFeedMessage)msg);
            else if (msg is DownloadMessage) ProcessMessage((DownloadMessage)msg);
            else if (msg is TestFeedMessage) ProcessMessage((TestFeedMessage)msg);
            else if (msg is AssignTagMessage) ProcessMessage((AssignTagMessage)msg);
            else if (msg is RemoveTagMessage) ProcessMessage((RemoveTagMessage)msg);
            else if (msg is InitEngineMessage) Initiation();
            //TODO:增加更多的消息类型
        }

        public void ProcessMessage(TestFeedMessage msg)
        {
            RssModel testRss = new RssModel();
            testRss.Load(msg.Link);
            msg.Result = testRss;
        }

        public void ProcessMessage(UpdateFeedMessage msg)
        {
            UpdateFeed();
        }

        public void ProcessMessage(IManagedXmlModelMessage msg)
        {
            ReaderWriterLock rwlock;
            IXmlModelProvider provider;
            if (msg.Item is RssFeedSource)
            {
                provider = Bus.FeedSourceProvider;
                rwlock = rwLockFeedSource;
            }
            else if (msg.Item is RssFilter)
            {
                provider = Bus.FilterProvider;
                rwlock = rwLockRssFilter;
            }
            else if (msg.Item is ResourceItem)
            {
                provider = Bus.ResourceProvider;
                rwlock = rwLockResource;
            }
            else if (msg.Item is SiteSchema)
            {
                provider = Bus.SchemaProvider;
                rwlock = rwLockSiteSchema;
            }
            else return;
            try
            {
                rwlock.AcquireWriterLock(RWLOCK_TIMEOUT);
                switch (msg.Type)
                {
                    case ActionType.Add:
                        provider.AddItem(msg.Item);
                        break;
                    case ActionType.Replace:
                        if (msg.Item.Id == -1)
                        {
                            msg.Item.Id = ((ReplaceItemMessage)msg).ItemToReplace.Id;
                        }
                        provider.RemoveItem(((ReplaceItemMessage)msg).ItemToReplace);
                        provider.AddItem(msg.Item);
                        break;
                    case ActionType.Delete:
                        provider.RemoveItem(msg.Item);
                        break;
                    case ActionType.Update:
                        //TODO:完善ResourceItem后可以刷新任何值
                        UpdateItemMessage tmpMsg = (UpdateItemMessage)msg;
                        if (provider == Bus.ResourceProvider && tmpMsg.Key == Constants.CONST_TAG_STATUS)
                        {
                            Bus.ResourceProvider.UpdateStatus((ResourceItem)tmpMsg.Item, tmpMsg.Value);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                        break;
                }
            }
            finally
            {
                rwlock.ReleaseWriterLock();
            }
        }

        public void ProcessMessage(DownloadMessage msg)
        {
            Bus.TracyDownloader.EnqueueMessage(msg);
        }
        public void ProcessMessage(AssignTagMessage msg)
        {
            msg.Relationship = Bus.TracyTagManager.AssignTag(msg.Property, msg.Source, msg.Target);
        }
        public void ProcessMessage(RemoveTagMessage msg)
        {
            if (msg.Relationship != null)
            {
                Bus.TracyTagManager.RemoveTag(msg.Relationship);
            }
            else if(msg.Source != null && msg.Target != null)
            {
                Bus.TracyTagManager.RemoveTag(msg.Source, msg.Target);
            }
        }

        #endregion

        void TracyDownloader_OnMessageProcessed(object sender, TracyMessageEventArgs e)
        {
            if (e.Message is DownloadMessage && e.Message.MessageException == null)
            {
                MessageGenerator.UpdateItem(e.Message.Sender, ((DownloadMessage)e.Message).Item, Constants.CONST_TAG_STATUS, Constants.CONST_RESOURCE_STATUS_SENTTODOWNLOAD);
            }
        }



    }


}